Knowledge bases for Amazon Bedrock で複数データソースを追加してみた
こんにちは、つくぼし(tsukuboshi0755)です!
今まで単一のデータソースしか設定できなかったKnowledge Bases for Amazon Bedrockに対して、以下のアップデートにより複数のデータソースを追加できるようになりました。
またデータソースとして今まで同じアカウント内に存在するS3バケットしか指定できなかったのですが、別アカウント内に存在するS3バケットも指定できるようになっています。
今回はKnowledge Bases for Amazon Bedrockに対する複数のデータソースの設定方法を紹介します!
複数データソースの追加方法
以下のナレッジベース作成画面における別のデータソースを追加
ボタンをクリックする事で、複数データソースを設定できます。
また既に作成済のナレッジベースでも、追加
ボタンをクリックする事で、複数データソースを設定できます。
データソースでは、今まで通り通り各S3バケットのURIを指定する事になります。
今回のアップデートにより、1つのナレッジベースにつき、最大5個のデータソースを指定できるようになっています。
また以下のData source locationでOther AWS Account
を選択し、アカウントIDを入力する事で、別アカウントのS3バケットも指定できるようになっています。
なおコンソールから別アカウントのS3バケットをデータソースとして設定する際は、事前に対象バケットに対して、以下のようなクロスアカウント用バケットポリシーを設定する必要があるのでご注意ください。
- バケットポリシー例
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "<ナレッジベースロールARN>" }, "Action": [ "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::<バケット名>" ] }, { "Effect": "Allow", "Principal": { "AWS": "<ナレッジベースロールARN>" }, "Action": [ "s3:GetObject" ], "Resource": [ "arn:aws:s3:::<バケット名及びプレフィックス>/*" ] } ] }
ナレッジベースから別アカウントのS3バケットにアクセスする方法の詳細については、以下の公式ドキュメントも合わせてご参照ください。
実際に複数データソースを追加してみる
データソースの1つを自アカウントのバケット(cm-test-kb-ds-bucket-<自アカウントID>)、もう1つを別アカウント(cm-test-kb-ds-bucket-<別アカウントID>)のバケットとする設定で、ナレッジベースを以下の通り作成してみました。
なお別アカウントのバケットと区別がつくように、自アカウントのバケットでデータソースを作成した場合、以下のように(this account)
という表示がつきます。
ナレッジベースの作成が完了しましたら、2つのデータソースで同期を実施し、正常に同期が完了する事を確認します。
なおデータの同期は、各々のデータソース毎に実施する必要があるためご注意ください。
データソースの同期が完了しましたら、動作確認のため右ペインにある「ナレッジベースをテスト」を実施します。
複数データソースでの動作を確認するため、事前に自アカウントのバケットにはAWS Lambda - 開発者ガイド、別アカウントのバケットにはAmazon Virtual Private Cloud - ユーザーガイドのドキュメントをアップロードしています。
例えば以下のようなLambdaに関する質問をすると、自アカウントのバケットに格納されているLambdaのドキュメントが検索結果に表示されます。
逆に以下のようなVPCに関する質問をすると、別アカウントのバケットに格納されているVPCのドキュメントが検索結果に表示されるようになります。
上記の動作確認で、複数データソースが正常に設定されている事が確認できました!
特定データソースのみを検索対象とする方法
ナレッジベースで複数データソースを設定できるようになった事で、今後特定のデータソースのみをナレッジベースの検索対象としたい場合もあるかと思います。
調査した所、APIでクエリを実行する事で追加の設定不要で実現できる事が分かったので、紹介します。
なお今回はベクターストアにOpenSearch Serverlessを使用した場合で動作検証しているため、他のサービスをベクターストアとして指定した場合は想定通りの挙動にならない可能性があります。
上記を踏まえた上でご参照頂けますと幸いです。
ナレッジベースを作成すると、以下のようにベクターストア(今回はOpenSearch Serverless)のデフォルトインデックスのメタデータとして、x-amz-bedrock-kb-source-uri
が自動で作成されます。
このx-amz-bedrock-kb-source-uri
に対する値として、各データソースのS3オブジェクトURIが格納されるようになります。
特定のデータソースのみを検索対象とする場合、startsWith
フィルタリングにてx-amz-bedrock-kb-source-uri
を指定し、パラメータにS3のURIを設定する事で、指定したS3のURIで始まるオブジェクトのみを検索対象として絞る事ができます。
フィルタリングについては、以下の公式ドキュメントも合わせてご参照ください。
具体的なコマンドとしては以下の通りです。
なおCloudShell上での実行を想定しています。
# ナレッジベースIDとS3バケットURIの値を置き換えてください KNOWLEDGE_BASE_ID=<ナレッジベースID> TEXT_MODEL_ARN=arn:aws:bedrock:${AWS_REGION}::foundation-model/anthropic.claude-3-haiku-20240307-v1:0 INPUT_TEXT=Lambda関数をVPC内に置く場合の注意点を教えてください S3_URI=<S3バケットURI> NUMBER_OF_RESULTS=5 aws bedrock-agent-runtime retrieve-and-generate \ --region ${AWS_REGION} \ --input text="${INPUT_TEXT}" \ --retrieve-and-generate-configuration "{\"knowledgeBaseConfiguration\":{\"knowledgeBaseId\":\"${KNOWLEDGE_BASE_ID}\",\"modelArn\":\"${TEXT_MODEL_ARN}\",\"retrievalConfiguration\":{\"vectorSearchConfiguration\":{\"filter\":{\"startsWith\":{\"key\":\"x-amz-bedrock-kb-source-uri\",\"value\":\"${S3_URI}\"}},\"numberOfResults\":${NUMBER_OF_RESULTS}}}},\"type\":\"KNOWLEDGE_BASE\"}"
上記コマンドは、BedrockAgentRuntime APIのRetriveAndGenerateメソッドを叩く際に、以下のJSON設定を渡す形になっています。
{ "knowledgeBaseConfiguration": { "knowledgeBaseId": "${KNOWLEDGE_BASE_ID}", "modelArn": "${TEXT_MODEL_ARN}", "retrievalConfiguration": { "vectorSearchConfiguration": { "filter": { "startsWith": { "key": "x-amz-bedrock-kb-source-uri", "value": "${S3_URI}" } }, "numberOfResults": ${NUMBER_OF_RESULT} } } }, "type": "KNOWLEDGE_BASE" }
例えば先ほど作成したナレッジベースのIDをKNOWLEDGE_BASE_ID
に指定し、コマンドを実行して挙動を確認して見ます。
先にS3_URI
に対して、AWS Lambda - 開発者ガイドが格納されている自アカウントのS3バケットURIを指定しコマンドを実行すると、以下のような結果になります。
{ "citations": [ { "generatedResponsePart": { "textResponsePart": { "span": { "end": 49, "start": 0 }, "text": "Lambda 関数を VPC Lattice ネットワーク内に配置する際の注意点は以下のとおりです:" } }, "retrievedReferences": [ { "content": { "text": "サービスを VPC Lattice ネットワーク内に配置すると、サー ビスの検出、接続、監視とサービスへのアクセスがより簡単になります。 トピック • VPC Lattice の概念 • 前提条件とアクセス許可 • 制限事項 • Lambda 関数を VPC Lattice ネットワークに登録する • VPC Lattice ネットワーク内のサービスのターゲットの更新 • Lambda 関数のターゲットを登録解除する • クロスアカウントネットワーク設定 • VPC Lattice からのイベントの受信 • VPC Lattice へのレスポンスの送信 • VPC Lattice ネットワーク でのサービスの監視 VPC Lattice の概念 このガイドでは、以下の VPC Lattice 用語を何度でも参照してください。 • サービス — サービスとは、インスタンス、コンテナ、またはサーバーレス関数内で実行できるソ フトウェアアプリケーションすべてを指します。このトピックでは、Lambda 関数を使用して構築 されたサービスのみを対象としています。 • サービスネットワーク — サービスネットワークは、サービスのネットワークを含む論理的な境界 です。このトピックでは、Lambda 関数を VPC Lattice サービスネットワーク内のサービスとして 設定する方法について説明します。 • ターゲットグループ — ターゲットグループは、サービスを実行するコンピュートタイプの宛先の コレクションです。Lambda のターゲットグループには、ターゲットとして 1 つの Lambda 関数 しか含めることができません。複数の関数を持つターゲットグループをターゲットにすることはで きません。 VPC Lattice 1426 https://docs.aws.amazon.com/vpc-lattice/latest/ug/service-networks.html https://docs.aws.amazon.com/vpc-lattice/latest/ug/how-it-works.html AWS Lambda 開発者ガイド • リスナー — リスナーは、トラフ ィックを受信し、サービスネットワーク内のさまざまなターゲッ トグループにルーティングするプロセスです。 • リスナールール — リスナールールには、リスナーがトラフィックのルーティング先を決定するた めに使用する優先度、アクション、および条件が含まれます。各リスナーにはデフォルトのリス ナールールがあり、1 つのリスナーに複数のリスナールールを設定できます。リスナールールには 次のものを含めることができます。 • プロトコル — リスナーがリクエストを宛先に送信するために使用するプロトコル。HTTP また は HTTPS のいずれか。 • ポート — リスナーが受信リクエストをポーリングするポート。1~65535 の範囲を使用できま す。 • パス — ターゲットリソースへのパス。デフォルトリスナールールでは、パスは / のデフォルト パスです。リスナールールには、デフォルトパスを含めて最大 6 つのパスを含めることができ ます。 • 優先度 — リスナーはパスの優先度を使用して、トラフィックをルーティングするパスを決定し ます。数字が小さいほど、優先順位が高くなります。デフォルトパスの優先度は最も低くなりま す。新しいパスを追加すると、VPC Lattice はデフォルトで 2 番目に低い優先度でそ のパスを割 り当てます。これはデフォルトパスの優先度を少し上回りますが、他のすべてのデフォルト以外 のパスよりは優先度が低くなります。 さらに、以下のAWS Identity and Access Management (IAM) エンティティについても覚えておきま しょう。 • ネットワークオーナー — VPC Lattice サービスネットワークを所有する IAM ロールです。 • サービスオーナー Lambda 関数を使用して構築されたサービスを所有する IAM ロールです。サー ビスオーナーとネットワークオーナーは同じエンティティである必要はありません。" }, "location": { "s3Location": { "uri": "s3://<自アカウントバケット名>/lambda-dg.pdf" }, "type": "S3" }, "metadata": { "x-amz-bedrock-kb-source-uri": "s3://<自アカウントバケット名>/lambda-dg.pdf" } } ] }, { "generatedResponsePart": { "textResponsePart": { "span": { "end": 213, "start": 51 }, "text": "- サービスの検出、接続、監視、アクセスが簡単になる\n- Lambda 関数のみをターゲットとすることができ、複数の関数を含むターゲットグループはサポートされていない\n- リスナールールを使用してトラフィックをターゲットグループにルーティングできる\n- ネットワークオーナーとサービスオーナーは同じエンティティである必要はない" } }, "retrievedReferences": [ { "content": { "text": "サービスを VPC Lattice ネットワーク内に配置すると、サー ビスの検出、接続、監視とサービスへのアクセスがより簡単になります。 トピック • VPC Lattice の概念 • 前提条件とアクセス許可 • 制限事項 • Lambda 関数を VPC Lattice ネットワークに登録する • VPC Lattice ネットワーク内のサービスのターゲットの更新 • Lambda 関数のターゲットを登録解除する • クロスアカウントネットワーク設定 • VPC Lattice からのイベントの受信 • VPC Lattice へのレスポンスの送信 • VPC Lattice ネットワーク でのサービスの監視 VPC Lattice の概念 このガイドでは、以下の VPC Lattice 用語を何度でも参照してください。 • サービス — サービスとは、インスタンス、コンテナ、またはサーバーレス関数内で実行できるソ フトウェアアプリケーションすべてを指します。このトピックでは、Lambda 関数を使用して構築 されたサービスのみを対象としています。 • サービスネットワーク — サービスネットワークは、サービスのネットワークを含む論理的な境界 です。このトピックでは、Lambda 関数を VPC Lattice サービスネットワーク内のサービスとして 設定する方法について説明します。 • ターゲットグループ — ターゲットグループは、サービスを実行するコンピュートタイプの宛先の コレクションです。Lambda のターゲットグループには、ターゲットとして 1 つの Lambda 関数 しか含めることができません。複数の関数を持つターゲットグループをターゲットにすることはで きません。 VPC Lattice 1426 https://docs.aws.amazon.com/vpc-lattice/latest/ug/service-networks.html https://docs.aws.amazon.com/vpc-lattice/latest/ug/how-it-works.html AWS Lambda 開発者ガイド • リスナー — リスナーは、トラフ ィックを受信し、サービスネットワーク内のさまざまなターゲッ トグループにルーティングするプロセスです。 • リスナールール — リスナールールには、リスナーがトラフィックのルーティング先を決定するた めに使用する優先度、アクション、および条件が含まれます。各リスナーにはデフォルトのリス ナールールがあり、1 つのリスナーに複数のリスナールールを設定できます。リスナールールには 次のものを含めることができます。 • プロトコル — リスナーがリクエストを宛先に送信するために使用するプロトコル。HTTP また は HTTPS のいずれか。 • ポート — リスナーが受信リクエストをポーリングするポート。1~65535 の範囲を使用できま す。 • パス — ターゲットリソースへのパス。デフォルトリスナールールでは、パスは / のデフォルト パスです。リスナールールには、デフォルトパスを含めて最大 6 つのパスを含めることができ ます。 • 優先度 — リスナーはパスの優先度を使用して、トラフィックをルーティングするパスを決定し ます。数字が小さいほど、優先順位が高くなります。デフォルトパスの優先度は最も低くなりま す。新しいパスを追加すると、VPC Lattice はデフォルトで 2 番目に低い優先度でそ のパスを割 り当てます。これはデフォルトパスの優先度を少し上回りますが、他のすべてのデフォルト以外 のパスよりは優先度が低くなります。 さらに、以下のAWS Identity and Access Management (IAM) エンティティについても覚えておきま しょう。 • ネットワークオーナー — VPC Lattice サービスネットワークを所有する IAM ロールです。 • サービスオーナー Lambda 関数を使用して構築されたサービスを所有する IAM ロールです。サー ビスオーナーとネットワークオーナーは同じエンティティである必要はありません。" }, "location": { "s3Location": { "uri": "s3://<自アカウントバケット名>/lambda-dg.pdf" }, "type": "S3" }, "metadata": { "x-amz-bedrock-kb-source-uri": "s3://<自アカウントバケット名>/lambda-dg.pdf" } } ] } ], "output": { "text": "Lambda 関数を VPC Lattice ネットワーク内に配置する際の注意点は以下のとおりです: - サービスの検出、接続、監視、アクセスが簡単になる\n- Lambda 関数のみをターゲットとすることができ、複数の関数を含むターゲットグループはサポートされていない\n- リスナールールを使用してトラフィックをターゲットグループにルーティングできる\n- ネットワークオーナーとサービスオーナーは同じエンティティである必要はない" }, "sessionId": "68a08d56-4867-4d98-89e4-aedd5f46a2ad" }
逆にS3_URI
に対して、Amazon Virtual Private Cloud - ユーザーガイドが格納されている別アカウントのS3バケットURIを指定しコマンドを実行すると、以下のような結果になります。
{ "citations": [ { "generatedResponsePart": { "textResponsePart": { "span": { "end": 38, "start": 0 }, "text": "AWS Lambda 関数を VPC 内に置く場合の注意点は以下のとおりです:" } }, "retrievedReferences": [ { "content": { "text": "• Windows Server 2008 以降のバージョンでは、ポート 49152~65535 を使用します。 • NAT ゲートウェイはポート 1024~65535 を使用します。 カスタムネットワーク ACL およびその他の AWS のサービス 443 https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-groups.html#elb-vpc-nacl https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-groups.html#elb-vpc-nacl Amazon Virtual Private Cloud ユーザーガイド • AWS Lambda 関数は、ポート 1024-65535 を使用します。 たとえば、インターネット上の Windows 10 クライアントから、お客様の VPC のウェブサーバーに リクエストが送信される場合、ネットワーク ACL には、ポート 49152 ~ 65535 宛てのトラフィッ クを可能にするアウトバウンドルールを用意する必要があります。 VPC 内のインスタンスが、リクエストを開始するクライアントの場合、ネットワーク ACL には、 インスタンス (Amazon Linux、Windows Server 2008 など) の種類に固有の一時ポートあてのトラ フィックを可能にするインバウンドルールを用意する必要があります。 実際に、VPC 内の パブリックに面したインスタンスに対して、トラフィックを開始することができ る多様なクライアントを対象にするには、一時ポート 1024~65535 を開くことができます。ただ し、その範囲内で悪意のあるポートのトラフィックを拒否するルールを ACL を追加することもでき ます。この とき、テーブル内で、幅広い範囲の一時ポートを開く許可ルールよりも先に拒否ルールを 配置します。 パス MTU 検出 2 つのデバイス間のパス MTU を判断するために、パス MTU 検出が使用されます。パス MTU は、送 信側ホストと受信側ホスト間のパスでサポートされている最大のパケットサイズです。 IPv4 の場合、ホストがパスに沿って送信するパケットが、受信側ホストの MTU、あるいはデバイ スの MTU よりも大きな場合、受信側ホストまたはデバイスはそのパケットをドロップし、次のよ うな ICMP メッセージ Destination Unreachable: Fragmentation Needed and Don't Fragment was Set (タイプ 3、コード 4) を返します。このメッセージは送信側ホストに対し、ペ イロードを複数の小さなパケットに分割し再送信することを指示します。 IPv6 プロトコルは、ネットワークのフラグメンテーションをサポートしていません。ホストがパ ス に沿って送信するパケットが、受信側ホストの MTU、あるいはデバイスの MTU よりも大きな 場合、受信側ホストまたはデバイスはそのパケットをドロップし、次のような ICMP メッセージ ICMPv6 Packet Too Big (PTB) (タイプ 2) を返します。このメッセージは送信側ホストに対 し、ペ イロードを複数の小さなパケットに分割し再送信することを指示します。 サブネット内のホスト間の最大送信単位 (MTU) が異なる場合、またはインスタンスがインターネッ ト経由でピアと通信する場合、インバウンドとアウトバウンドの両方に、以下のネットワーク ACL ルールを追加 する必要があります。これにより、パス MTU 検出が正しく機能し、パケット損失を 防ぐことができます。タイプに [Custom ICMP Rule] を選択し、ポート範囲(タイプ 3、コード 4) に [送信先に到達できません]、[fragmentation required, and DF flag set (フラグメンテーションが必 要、および DF フラグを設定)] を選択します。" }, "location": { "s3Location": { "uri": "s3://<別アカウントバケット名>/vpc-ug.pdf" }, "type": "S3" }, "metadata": { "x-amz-bedrock-kb-source-uri": "s3://<別アカウントバケット名>/vpc-ug.pdf" } } ] }, { "generatedResponsePart": { "textResponsePart": { "span": { "end": 163, "start": 40 }, "text": "- AWS Lambda 関数は、ポート 1024-65535 を使用します。そのため、VPC 内のインスタンスが Lambda 関数にアクセスする際は、ネットワーク ACL にインバウンドルールを設定し、この範囲のポートを許可する必要があります。" } }, "retrievedReferences": [ { "content": { "text": "• Windows Server 2008 以降のバージョンでは、ポート 49152~65535 を使用します。 • NAT ゲートウェイはポート 1024~65535 を使用します。 カスタムネットワーク ACL およびその他の AWS のサービス 443 https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-groups.html#elb-vpc-nacl https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-groups.html#elb-vpc-nacl Amazon Virtual Private Cloud ユーザーガイド • AWS Lambda 関数は、ポート 1024-65535 を使用します。 たとえば、インターネット上の Windows 10 クライアントから、お客様の VPC のウェブサーバーに リクエストが送信される場合、ネットワーク ACL には、ポート 49152 ~ 65535 宛てのトラフィッ クを可能にするアウトバウンドルールを用意する必要があります。 VPC 内のインスタンスが、リクエストを開始するクライアントの場合、ネットワーク ACL には、 インスタンス (Amazon Linux、Windows Server 2008 など) の種類に固有の一時ポートあてのトラ フィックを可能にするインバウンドルールを用意する必要があります。 実際に、VPC 内の パブリックに面したインスタンスに対して、トラフィックを開始することができ る多様なクライアントを対象にするには、一時ポート 1024~65535 を開くことができます。ただ し、その範囲内で悪意のあるポートのトラフィックを拒否するルールを ACL を追加することもでき ます。この とき、テーブル内で、幅広い範囲の一時ポートを開く許可ルールよりも先に拒否ルールを 配置します。 パス MTU 検出 2 つのデバイス間のパス MTU を判断するために、パス MTU 検出が使用されます。パス MTU は、送 信側ホストと受信側ホスト間のパスでサポートされている最大のパケットサイズです。 IPv4 の場合、ホストがパスに沿って送信するパケットが、受信側ホストの MTU、あるいはデバイ スの MTU よりも大きな場合、受信側ホストまたはデバイスはそのパケットをドロップし、次のよ うな ICMP メッセージ Destination Unreachable: Fragmentation Needed and Don't Fragment was Set (タイプ 3、コード 4) を返します。このメッセージは送信側ホストに対し、ペ イロードを複数の小さなパケットに分割し再送信することを指示します。 IPv6 プロトコルは、ネットワークのフラグメンテーションをサポートしていません。ホストがパ ス に沿って送信するパケットが、受信側ホストの MTU、あるいはデバイスの MTU よりも大きな 場合、受信側ホストまたはデバイスはそのパケットをドロップし、次のような ICMP メッセージ ICMPv6 Packet Too Big (PTB) (タイプ 2) を返します。このメッセージは送信側ホストに対 し、ペ イロードを複数の小さなパケットに分割し再送信することを指示します。 サブネット内のホスト間の最大送信単位 (MTU) が異なる場合、またはインスタンスがインターネッ ト経由でピアと通信する場合、インバウンドとアウトバウンドの両方に、以下のネットワーク ACL ルールを追加 する必要があります。これにより、パス MTU 検出が正しく機能し、パケット損失を 防ぐことができます。タイプに [Custom ICMP Rule] を選択し、ポート範囲(タイプ 3、コード 4) に [送信先に到達できません]、[fragmentation required, and DF flag set (フラグメンテーションが必 要、および DF フラグを設定)] を選択します。" }, "location": { "s3Location": { "uri": "s3://<別アカウントバケット名>/vpc-ug.pdf" }, "type": "S3" }, "metadata": { "x-amz-bedrock-kb-source-uri": "s3://<別アカウントバケット名>/vpc-ug.pdf" } } ] } ], "output": { "text": "AWS Lambda 関数を VPC 内に置く場合の注意点は以下のとおりです: - AWS Lambda 関数は、ポート 1024-65535 を使用します。そのため、VPC 内のインスタンスが Lambda 関数にアクセスする際は、ネットワーク ACL にインバウンドルールを設定し、この範囲のポートを 許可する必要があります。" }, "sessionId": "7ffff79b-3355-4a14-af05-2fd8df9d5852" }
上記の通り、特定のデータソースで指定されているS3バケットのみを検索対象として、回答を生成する事ができました!
(2024/5/2追記)以下の公式ブログでも同じような検索方法が記載されていると教えて頂いたので、こちらも合わせてご参照ください!
なおS3バケット単位ではなく、各ドキュメントに対して独自のタグを定義しより複雑なクエリを実施したい場合は、別途メタデータを追加で設定する事で実現できます。
メタデータフィルタリングの詳細については、以下のブログをご確認ください。
最後に
今回は、Knowledge Bases for Amazon Bedrockに対する複数のデータソースの設定方法を紹介しました。
複数のデータソースがサポートされた事により、バケット毎に異なるタイプのドキュメントを格納し、RAGシステムを構築する事が可能になりました。
また別アカウントのバケットをデータソースとして設定する事で、異なるアカウントに存在するデータを用いて検索する事も容易になっています。
RAGについてご関心がある方は、ぜひ今回のアップデートを一度お試ししてみてはいかがでしょうか。
以上、つくぼし(tsukuboshi0755)でした!